package db

import (
	"fmt"
	gormadapter "github.com/casbin/gorm-adapter/v3"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"os"
	"server/config"
	"server/model"
	"time"

	uuid "github.com/satori/go.uuid"
)

/*
数据库模块初始化
*/

var (
	DB *gorm.DB
)

func InitMysql(m config.Mysql) {

	dsn := m.Username + ":" + m.Password + "@tcp(" + m.Addr + ")/" + m.Dbname + "?" + m.Config
	mysqlConfig := mysql.Config{
		DSN:                       dsn,   // DSN data source name
		DefaultStringSize:         191,   // string 类型字段的默认长度
		DisableDatetimePrecision:  true,  // 禁用 datetime 精度，MySQL 5.6 之前的数据库不支持
		DontSupportRenameIndex:    true,  // 重命名索引时采用删除并新建的方式，MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
		DontSupportRenameColumn:   true,  // 用 `change` 重命名列，MySQL 8 之前的数据库和 MariaDB 不支持重命名列
		SkipInitializeWithVersion: false, // 根据版本自动配置
	}
	if db, err := gorm.Open(mysql.New(mysqlConfig), gormConfig(m.LogMode)); err != nil {
		fmt.Printf("MySQL启动异常,error is %v\n", err)
		os.Exit(0)
	} else {
		sqlDB, _ := db.DB()
		sqlDB.SetMaxIdleConns(m.MaxIdleConns)
		sqlDB.SetMaxOpenConns(m.MaxOpenConns)
		DB = db
	}
}

func gormConfig(mod bool) *gorm.Config {

	if mod {
		return &gorm.Config{
			Logger:                                   logger.Default.LogMode(logger.Info),
			DisableForeignKeyConstraintWhenMigrating: true,
		}
	} else {
		return &gorm.Config{
			Logger:                                   logger.Default.LogMode(logger.Silent),
			DisableForeignKeyConstraintWhenMigrating: true,
		}
	}
}

func MysqlTables(db *gorm.DB) {
	err := db.AutoMigrate(
		model.SysUser{},
		model.Blacklist{},
		model.SysRole{},
	)
	if err != nil {
		fmt.Printf("register table failed err is %v\n", err)
		os.Exit(0)
	}
	fmt.Println("register table success")
}

// 系统数据注入

func initSysUser(db *gorm.DB) {
	var Users = []model.SysUser{
		model.SysUser{
			Base: model.Base{
				ID: 1, CreatedAt: time.Now(), UpdatedAt: time.Now(),
			},
			UUID:     uuid.NewV4().String(),
			Username: "admin",
			Password: "21232f297a57a5a743894a0e4a801fc3",
			NickName: "超级管理员",
			RoleId:   "888",
		},
		model.SysUser{
			Base: model.Base{
				ID: 2, CreatedAt: time.Now(), UpdatedAt: time.Now(),
			},
			UUID:     uuid.NewV4().String(),
			Username: "kaka",
			Password: "5541c7b5a06c39b267a5efae6628e003",
			NickName: "testUser",
			RoleId:   "9528",
		},
	}

	if err := db.Transaction(func(tx *gorm.DB) error {
		if tx.Where("id IN ?", []int{1, 2}).Find(&[]model.SysUser{}).RowsAffected == 2 {
			fmt.Println("sys_users表的初始数据已存在!")
			return nil
		}
		if err := tx.Create(&Users).Error; err != nil { // 遇到错误时回滚事务
			return err
		}
		return nil
	}); err != nil {
		fmt.Printf("[Mysql]--> sys_users 表的初始数据失败,err: %v\n", err)
		os.Exit(0)
	}
}

func initSysRole(db *gorm.DB) {

	var Roles = []model.SysRole{
		{CreatedAt: time.Now(), UpdatedAt: time.Now(), RoleId: "888", RoleName: "普通用户", ParentId: "0"},
		{CreatedAt: time.Now(), UpdatedAt: time.Now(), RoleId: "8881", RoleName: "普通用户子角色", ParentId: "888"},
		{CreatedAt: time.Now(), UpdatedAt: time.Now(), RoleId: "9528", RoleName: "测试角色", ParentId: "0"},
	}
	if err := db.Transaction(func(tx *gorm.DB) error {
		if tx.Where("role_id IN ? ", []string{"888", "9528"}).Find(&[]model.SysRole{}).RowsAffected == 2 {
			fmt.Println("sys_roles表的初始数据已存在!")
			return nil
		}
		if err := tx.Create(&Roles).Error; err != nil { // 遇到错误时回滚事务
			return err
		}
		return nil
	}); err != nil {
		fmt.Printf("[Mysql]--> sys_roles 表的初始数据失败,err: %v\n", err)
		os.Exit(0)
	}
}

func initCasbinModel(db *gorm.DB) {
	var carbines = []gormadapter.CasbinRule{

		{PType: "p", V0: "888", V1: "/base/login", V2: "POST"},
		{PType: "p", V0: "888", V1: "/jwt/setInBlacklist", V2: "POST"},
		{PType: "p", V0: "888", V1: "/user/register", V2: "POST"},
		{PType: "p", V0: "888", V1: "/user/changePassword", V2: "PUT"},
		{PType: "p", V0: "888", V1: "/user/getUserList", V2: "GET"},
		{PType: "p", V0: "888", V1: "/user/getUserInfo", V2: "GET"},
		{PType: "p", V0: "888", V1: "/user/changeUserRole", V2: "PUT"},
		{PType: "p", V0: "888", V1: "/user/deleteUser", V2: "DELETE"},
		{PType: "p", V0: "888", V1: "/casbin/updateCasbin", V2: "PUT"},
		{PType: "p", V0: "888", V1: "/casbin/getPolicy", V2: "GET"},
		{PType: "p", V0: "888", V1: "/role/createRole", V2: "POST"},
		{PType: "p", V0: "888", V1: "/role/deleteRole", V2: "DELETE"},
		{PType: "p", V0: "888", V1: "/role/getRoleInfo", V2: "GET"},

		{PType: "p", V0: "8881", V1: "/casbin/getPolicy", V2: "GET"},
		{PType: "p", V0: "8881", V1: "/user/changePassword", V2: "PUT"},
		{PType: "p", V0: "8881", V1: "/user/getUserList", V2: "GET"},
		{PType: "p", V0: "8881", V1: "/user/deleteUser", V2: "DELETE"},

		{PType: "p", V0: "9528", V1: "/user/changePassword", V2: "PUT"},
		{PType: "p", V0: "9528", V1: "/user/getUserList", V2: "GET"},
		{PType: "p", V0: "9528", V1: "/user/deleteUser", V2: "DELETE"},
	}

	if err := db.Transaction(func(tx *gorm.DB) error {
		if tx.Table("casbin_rule").Where("p_type = ? AND v0 IN ?", "p", []string{"888", "8881", "9528"}).Find(&[]gormadapter.CasbinRule{}).RowsAffected == int64(len(carbines)) {
			fmt.Println("casbin_rule表的初始数据已存在!")
			return nil
		}
		if err := tx.Table("casbin_rule").Create(&carbines).Error; err != nil { // 遇到错误时回滚事务
			return err
		}
		return nil
	}); err != nil {
		fmt.Printf("[Mysql]--> casbin_rule 表的初始数据失败,err: %v\n", err)
		os.Exit(0)
	}
}

func SetTableData(db *gorm.DB) {
	initSysRole(db)
	initSysUser(db)
	initCasbinModel(db)

}
